import { TFunction } from 'i18next';

import { getNanoid } from '@/pages/chat/tools/tools';
import { AppChatConfigType, NodeStatusEnum } from '@/types/app/type';
import {
  defaultNodeVersion,
  EDGE_TYPE,
  FlowNodeInputTypeEnum,
  FlowNodeOutputTypeEnum,
  FlowNodeTypeEnum,
  NodeInputKeyEnum,
  NodeOutputKeyEnum,
  VARIABLE_NODE_ID,
  WorkflowIOValueTypeEnum,
} from '@/types/workflow/constant';
import { StoreEdgeItemType } from '@/types/workflow/edge';
import {
  FlowNodeInputItemType,
  FlowNodeOutputItemType,
  ReferenceValueProps,
} from '@/types/workflow/io';
import {
  FlowNodeItemType,
  FlowNodeTemplateType,
  StoreNodeItemType,
  WorkflowCheckListNodeResultType,
  WorkflowCheckListType,
} from '@/types/workflow/node';
import { moduleTemplatesFlat } from '@/types/workflow/template/constants';
import { EmptyNode } from '@/types/workflow/template/system/emptyNode';
import { VariableConditionEnum } from '@/types/workflow/template/system/ifElse/constant';
import { IfElseListItemType } from '@/types/workflow/template/system/ifElse/type';

import type { Edge, Node, XYPosition } from 'reactflow';
import { getGlobalVariableNode } from './adapt';
import { EditorVariablePickerType } from '@/types/workflow/components/common/Textarea/PromptEditor/type';
import {
  formatEditorVariablePickerIcon,
  getAppChatConfig,
  getGuideModule,
} from '@/types/workflow/utils';
import { workflowSystemVariables } from '../app/utils';

import { cloneDeep, isEqual } from 'lodash';
import { getInputComponentProps } from './node/io/utils';
import { NodeCardProps } from '@/pages/app/detail/components/Workflow/components/nodes/render/NodeCard';
import { LLMModelItemType } from '@/types/ai/model';

export const nodeTemplate2FlowNode = ({
  template,
  position,
  selected,
  parentNodeId,
  zIndex,
  t,
}: {
  template: FlowNodeTemplateType;
  position: XYPosition;
  selected?: boolean;
  parentNodeId?: string;
  zIndex?: number;
  t: TFunction;
}): Node<FlowNodeItemType> => {
  // replace item data
  const moduleItem: FlowNodeItemType = {
    ...template,
    name: t(template.name as any),
    nodeId: getNanoid(),
    parentNodeId,
  };

  return {
    id: moduleItem.nodeId,
    type: moduleItem.flowNodeType,
    data: moduleItem,
    position,
    selected,
    zIndex,
  };
};
export const storeNode2FlowNode = ({
  item: storeNode,
  selected = false,
  zIndex,
  parentNodeId,
  t,
}: {
  item: StoreNodeItemType;
  selected?: boolean;
  zIndex?: number;
  parentNodeId?: string;
  t: TFunction;
}): Node<FlowNodeItemType> => {
  // init some static data
  const template =
    moduleTemplatesFlat.find((template) => template.flowNodeType === storeNode.flowNodeType) ||
    EmptyNode;

  const templateInputs = template.inputs.filter((input) => !input.canEdit);
  const templateOutputs = template.outputs.filter(
    (output) => output.type !== FlowNodeOutputTypeEnum.dynamic,
  );
  const dynamicInput = template.inputs.find(
    (input) => input.renderTypeList[0] === FlowNodeInputTypeEnum.addInputParam,
  );

  // replace item data
  const nodeItem: FlowNodeItemType = {
    parentNodeId,
    ...template,
    ...storeNode,
    avatar: template.avatar || '' || storeNode.avatar,
    version: storeNode.version ?? template.version ?? defaultNodeVersion,
    /* 
      Inputs and outputs, New fields are added, not reduced
    */
    inputs: templateInputs
      .map<FlowNodeInputItemType>((templateInput) => {
        const storeInput =
          storeNode.inputs.find((item) => item.key === templateInput.key) || templateInput;

        return {
          ...storeInput,
          ...templateInput,

          debugLabel: t(templateInput.debugLabel ?? (storeInput.debugLabel as any)),
          toolDescription: t(templateInput.toolDescription ?? (storeInput.toolDescription as any)),

          selectedTypeIndex: storeInput.selectedTypeIndex ?? templateInput.selectedTypeIndex,
          value: storeInput.value ?? templateInput.value,
          label: storeInput.label ?? templateInput.label,
        };
      })
      .concat(
        /* Concat dynamic inputs */
        storeNode.inputs
          .filter((item) => !templateInputs.find((input) => input.key === item.key))
          .map((item) => {
            if (!dynamicInput) return item;

            return {
              ...item,
              ...getInputComponentProps(dynamicInput),
            };
          }),
      ),
    outputs: templateOutputs
      .map<FlowNodeOutputItemType>((templateOutput) => {
        const storeOutput =
          template.outputs.find((item) => item.key === templateOutput.key) || templateOutput;

        return {
          ...storeOutput,
          ...templateOutput,

          description: t(templateOutput.description ?? (storeOutput.description as any)),

          id: storeOutput.id ?? templateOutput.id,
          label: storeOutput.label ?? templateOutput.label,
          value: storeOutput.value ?? templateOutput.value,
        };
      })
      .concat(
        storeNode.outputs.filter(
          (item) => !templateOutputs.find((output) => output.key === item.key),
        ),
      ),
  };

  return {
    id: storeNode.nodeId,
    type: storeNode.flowNodeType,
    data: nodeItem,
    selected,
    position: storeNode.position || { x: 0, y: 0 },
    zIndex,
  };
};
export const storeEdgesRenderEdge = ({ edge }: { edge: StoreEdgeItemType }) => {
  return {
    ...edge,
    id: getNanoid(),
    type: EDGE_TYPE,
  };
};

export const computedNodeInputReference = ({
  nodeId,
  nodes,
  edges,
  chatConfig,
  t,
}: {
  nodeId: string;
  nodes: FlowNodeItemType[];
  edges: Edge[];
  chatConfig: AppChatConfigType;
  t: TFunction;
}) => {
  // get current node
  const node = nodes.find((item) => item.nodeId === nodeId);
  if (!node) {
    return;
  }
  const parentId = node.parentNodeId;
  const sourceNodes: FlowNodeItemType[] = [];
  // 根据 edge 获取所有的 source 节点（source节点会继续向前递归获取）
  const findSourceNode = (nodeId: string) => {
    const targetEdges = edges.filter((item) => item.target === nodeId || item.target === parentId);
    targetEdges.forEach((edge) => {
      const sourceNode = nodes.find((item) => item.nodeId === edge.source);
      if (!sourceNode) return;

      // 去重
      if (sourceNodes.some((item) => item.nodeId === sourceNode.nodeId)) {
        return;
      }
      sourceNodes.push(sourceNode);
      findSourceNode(sourceNode.nodeId);
    });
  };
  findSourceNode(nodeId);

  sourceNodes.push(
    getGlobalVariableNode({
      nodes,
      t,
      chatConfig,
    }),
  );

  return sourceNodes;
};
export const getRefData = ({
  variable,
  nodeList,
  chatConfig,
}: {
  variable?: ReferenceValueProps;
  nodeList: FlowNodeItemType[];
  chatConfig: AppChatConfigType;
}) => {
  if (!variable)
    return {
      valueType: WorkflowIOValueTypeEnum.any,
      required: false,
    };

  const node = nodeList.find((node) => node.nodeId === variable[0]);
  const systemVariables = getWorkflowGlobalVariables({ nodes: nodeList, chatConfig });

  if (!node) {
    const globalVariable = systemVariables.find((item) => item.key === variable?.[1]);
    return {
      valueType: globalVariable?.valueType || WorkflowIOValueTypeEnum.any,
      required: !!globalVariable?.required,
    };
  }

  const output = node.outputs.find((item) => item.id === variable[1]);
  if (!output)
    return {
      valueType: WorkflowIOValueTypeEnum.any,
      required: false,
    };

  return {
    valueType: output.valueType,
    required: !!output.required,
  };
};

/* Connection rules */
export const checkWorkflowNodeAndConnection = ({
  nodes,
  edges,
}: {
  nodes: Node<FlowNodeItemType, string | undefined>[];
  edges: Edge<any>[];
}): string[] | undefined => {
  // 1. reference check. Required value
  for (const node of nodes) {
    const { data } = node;
    const { inputs } = data;
    const isToolNode = edges.some(
      (edge) =>
        edge.targetHandle === NodeOutputKeyEnum.selectedTools && edge.target === node.data.nodeId,
    );

    if (
      data.flowNodeType === FlowNodeTypeEnum.systemConfig ||
      data.flowNodeType === FlowNodeTypeEnum.pluginConfig ||
      data.flowNodeType === FlowNodeTypeEnum.pluginInput ||
      data.flowNodeType === FlowNodeTypeEnum.workflowStart ||
      data.flowNodeType === FlowNodeTypeEnum.comment
    ) {
      continue;
    }

    if (data.flowNodeType === FlowNodeTypeEnum.ifElseNode) {
      const ifElseList: IfElseListItemType[] = inputs.find(
        (input) => input.key === NodeInputKeyEnum.ifElseList,
      )?.value;
      if (
        ifElseList.some((item) => {
          return item.list.some((listItem) => {
            return (
              listItem.variable === undefined ||
              listItem.condition === undefined ||
              (listItem.value === undefined &&
                listItem.condition !== VariableConditionEnum.isEmpty &&
                listItem.condition !== VariableConditionEnum.isNotEmpty)
            );
          });
        })
      ) {
        return [data.nodeId];
      }
      continue;
    }

    // check node input
    if (
      inputs.some((input) => {
        // check is tool input
        if (isToolNode && input.toolDescription) {
          return false;
        }

        if (input.required) {
          if (Array.isArray(input.value) && input.value.length === 0) return true;
          if (input.value === undefined) return true;
        }

        // check reference invalid
        const renderType = input.renderTypeList[input.selectedTypeIndex || 0];
        if (renderType === FlowNodeInputTypeEnum.reference && input.required) {
          if (!input.value || !Array.isArray(input.value) || input.value.length !== 2) {
            return true;
          }

          // variable key not need to check
          if (input.value[0] === VARIABLE_NODE_ID) {
            return false;
          }

          // Can not find key
          const sourceNode = nodes.find((item) => item.data.nodeId === input.value[0]);
          if (!sourceNode) {
            return true;
          }
          const sourceOutput = sourceNode.data.outputs.find((item) => item.id === input.value[1]);
          if (!sourceOutput) {
            return true;
          }
        }
        return false;
      })
    ) {
      return [data.nodeId];
    }

    // filter tools node edge
    const edgeFilted = edges.filter(
      (edge) =>
        !(
          data.flowNodeType === FlowNodeTypeEnum.tools &&
          edge.sourceHandle === NodeOutputKeyEnum.selectedTools
        ),
    );
    // check node has edge
    const hasEdge = edgeFilted.some(
      (edge) => edge.source === data.nodeId || edge.target === data.nodeId,
    );
    if (!hasEdge) {
      return [data.nodeId];
    }
  }
};

export const filterSensitiveNodesData = (nodes: StoreNodeItemType[]) => {
  const cloneNodes = JSON.parse(JSON.stringify(nodes)) as StoreNodeItemType[];

  cloneNodes.forEach((node) => {
    // selected dataset
    if (node.flowNodeType === FlowNodeTypeEnum.datasetSearchNode) {
      node.inputs.forEach((input) => {
        if (input.key === NodeInputKeyEnum.datasetSelectList) {
          input.value = [];
        }
      });
    }

    return node;
  });
  return cloneNodes;
};

/* get workflowStart output to global variables */
export const getWorkflowGlobalVariables = ({
  nodes,
  chatConfig,
}: {
  nodes: FlowNodeItemType[];
  chatConfig: AppChatConfigType;
}): EditorVariablePickerType[] => {
  const globalVariables = formatEditorVariablePickerIcon(
    getAppChatConfig({
      chatConfig,
      systemConfigNode: getGuideModule(nodes),
      isPublicFetch: true,
    })?.variables || [],
  );

  return [...globalVariables, ...workflowSystemVariables];
};

export type CombinedItemType = Partial<FlowNodeInputItemType> & Partial<FlowNodeOutputItemType>;

/* Reset node to latest version */
export const getLatestNodeTemplate = (
  node: FlowNodeItemType,
  template: FlowNodeTemplateType,
): FlowNodeItemType => {
  const updatedNode: FlowNodeItemType = {
    ...node,
    ...template,
    inputs: template.inputs.map((templateItem) => {
      const nodeItem = node.inputs.find((item) => item.key === templateItem.key);
      if (nodeItem) {
        return {
          ...templateItem,
          value: nodeItem.value,
          selectedTypeIndex: nodeItem.selectedTypeIndex,
          valueType: nodeItem.valueType,
        };
      }
      return { ...templateItem };
    }),
    outputs: template.outputs.map((templateItem) => {
      const nodeItem = node.outputs.find((item) => item.key === templateItem.key);
      if (nodeItem) {
        return {
          ...templateItem,
          id: nodeItem.id,
          value: nodeItem.value,
          valueType: nodeItem.valueType,
        };
      }
      return { ...templateItem };
    }),
    name: node.name,
    intro: node.intro,
  };

  return updatedNode;
};

export const compareSnapshot = (
  snapshot1: {
    nodes?: Node[];
    edges: Edge<any>[] | undefined;
    chatConfig?: AppChatConfigType;
  },
  snapshot2: {
    nodes?: Node[];
    edges: Edge<any>[];
    chatConfig?: AppChatConfigType;
  },
) => {
  const clone1 = cloneDeep(snapshot1);
  const clone2 = cloneDeep(snapshot2);

  if (!clone1.nodes || !clone2.nodes) return false;
  const formatEdge = (edges: Edge[] | undefined) => {
    if (!edges) return [];
    return edges.map((edge) => ({
      source: edge.source,
      target: edge.target,
      sourceHandle: edge.sourceHandle,
      targetHandle: edge.targetHandle,
      type: edge.type,
    }));
  };

  if (!isEqual(formatEdge(clone1.edges), formatEdge(clone2.edges))) {
    console.log('Edge not equal');
    return false;
  }

  if (
    clone1.chatConfig &&
    clone2.chatConfig &&
    !isEqual(
      {
        welcomeText: clone1.chatConfig?.welcomeText || '',
        variables: clone1.chatConfig?.variables || [],
        questionGuide: clone1.chatConfig?.questionGuide || false,
        ttsConfig: clone1.chatConfig?.ttsConfig || undefined,
        whisperConfig: clone1.chatConfig?.whisperConfig || undefined,
        scheduledTriggerConfig: clone1.chatConfig?.scheduledTriggerConfig || undefined,
        chatInputGuide: clone1.chatConfig?.chatInputGuide || undefined,
        fileSelectConfig: clone1.chatConfig?.fileSelectConfig || undefined,
        instruction: clone1.chatConfig?.instruction || '',
        hotQuestionConfig: clone1.chatConfig?.hotQuestionConfig || undefined,
      },
      {
        welcomeText: clone2.chatConfig?.welcomeText || '',
        variables: clone2.chatConfig?.variables || [],
        questionGuide: clone2.chatConfig?.questionGuide || false,
        ttsConfig: clone2.chatConfig?.ttsConfig || undefined,
        whisperConfig: clone2.chatConfig?.whisperConfig || undefined,
        scheduledTriggerConfig: clone2.chatConfig?.scheduledTriggerConfig || undefined,
        chatInputGuide: clone2.chatConfig?.chatInputGuide || undefined,
        fileSelectConfig: clone2.chatConfig?.fileSelectConfig || undefined,
        instruction: clone2.chatConfig?.instruction || '',
        hotQuestionConfig: clone2.chatConfig?.hotQuestionConfig || undefined,
      },
    )
  ) {
    console.log('chatConfig not equal');
    return false;
  }

  const formatNodes = (nodes: Node[]) => {
    return nodes
      .filter((node) => {
        if (!node) return;
        if (FlowNodeTypeEnum.systemConfig === node.type) return;

        return true;
      })
      .map((node) => ({
        id: node.id,
        type: node.type,
        position: node.position,
        data: {
          id: node.data.id,
          flowNodeType: node.data.flowNodeType,
          inputs: node.data.inputs.map((input: FlowNodeInputItemType) => ({
            key: input.key,
            selectedTypeIndex: input.selectedTypeIndex ?? 0,
            renderTypeLis: input.renderTypeList,
            valueType: input.valueType,
            value: input.value ?? undefined,
          })),
          outputs: node.data.outputs.map((item: FlowNodeOutputItemType) => ({
            key: item.key,
            type: item.type,
            value: item.value ?? undefined,
          })),
          name: node.data.name,
          intro: node.data.intro,
          avatar: node.data.avatar,
          version: node.data.version,
          isFolded: node.data.isFolded,
        },
      }));
  };
  const node1 = formatNodes(clone1.nodes);
  const node2 = formatNodes(clone2.nodes);

  node1.forEach((node, i) => {
    if (!isEqual(node, node2[i])) {
      console.log('node not equal', node, node2[i]);
    }
  });

  return isEqual(node1, node2);
};

/* Check single node validation */
export const checkSingleNode = ({
  node,
  nodes,
  edges,
}: {
  node: NodeCardProps;
  nodes: Node<FlowNodeItemType, string | undefined>[];
  edges: Edge<any>[];
}): {
  isValid: boolean;
  errorType?: 'input' | 'connection' | 'ifElse';
} => {
  const { inputs } = node;
  const isToolNode = edges.some(
    (edge) => edge.targetHandle === NodeOutputKeyEnum.selectedTools && edge.target === node.nodeId,
  );

  // 跳过系统节点检查
  if (
    node.flowNodeType === FlowNodeTypeEnum.systemConfig ||
    node.flowNodeType === FlowNodeTypeEnum.pluginConfig ||
    node.flowNodeType === FlowNodeTypeEnum.pluginInput ||
    node.flowNodeType === FlowNodeTypeEnum.workflowStart ||
    node.flowNodeType === FlowNodeTypeEnum.comment
  ) {
    return { isValid: true };
  }

  // 检查 if-else 节点
  if (node.flowNodeType === FlowNodeTypeEnum.ifElseNode) {
    const ifElseList: IfElseListItemType[] = inputs.find(
      (input) => input.key === NodeInputKeyEnum.ifElseList,
    )?.value;

    if (
      ifElseList?.some((item) => {
        return item.list.some((listItem) => {
          return (
            listItem.variable === undefined ||
            listItem.condition === undefined ||
            (listItem.value === undefined &&
              listItem.condition !== VariableConditionEnum.isEmpty &&
              listItem.condition !== VariableConditionEnum.isNotEmpty)
          );
        });
      })
    ) {
      return { isValid: false, errorType: 'ifElse' };
    }
    return { isValid: true };
  }

  // 检查节点输入
  if (
    inputs.some((input) => {
      // 检查工具输入
      if (isToolNode && input.toolDescription) {
        return false;
      }

      if (input.required) {
        if (Array.isArray(input.value) && input.value.length === 0) return true;
        if (input.value === undefined) return true;
      }

      // 检查引用是否有效
      const renderType = input.renderTypeList[input.selectedTypeIndex || 0];
      if (renderType === FlowNodeInputTypeEnum.reference && input.required) {
        if (!input.value || !Array.isArray(input.value) || input.value.length !== 2) {
          return true;
        }

        // 变量键不需要检查
        if (input.value[0] === VARIABLE_NODE_ID) {
          return false;
        }

        // 检查是否能找到源节点
        const sourceNode = nodes.find((item) => item.data.nodeId === input.value[0]);
        if (!sourceNode) {
          return true;
        }
        const sourceOutput = sourceNode.data.outputs.find((item) => item.id === input.value[1]);
        if (!sourceOutput) {
          return true;
        }
      }
      return false;
    })
  ) {
    return { isValid: false, errorType: 'input' };
  }

  // 过滤工具节点边
  const edgeFilted = edges.filter(
    (edge) =>
      !(
        node.flowNodeType === FlowNodeTypeEnum.tools &&
        edge.sourceHandle === NodeOutputKeyEnum.selectedTools
      ),
  );

  // 检查节点是否有边连接
  const hasEdge = edgeFilted.some(
    (edge) => edge.source === node.nodeId || edge.target === node.nodeId,
  );

  return {
    isValid: hasEdge,
    errorType: hasEdge ? undefined : 'connection',
  };
};

export const checkInputsValidCount = (inputs: FlowNodeInputItemType[]) => {
  const invalidCount = inputs.filter((input) => {
    if (Array.isArray(input.value) && input.value.length === 0) return true;
    if (input.value === undefined) return true;

    return false;
  }).length;

  return {
    invalidCount: invalidCount,
    validCount: inputs.length - invalidCount,
  };
};

/* 详细检查节点，返回所有检查项结果 */
export const checkNodeWithDetails = ({
  node,
  nodes,
  edges,
  llmModelList = [],
}: {
  node: NodeCardProps;
  nodes: Node<FlowNodeItemType, string | undefined>[];
  edges: Edge<any>[];
  llmModelList: LLMModelItemType[];
}): WorkflowCheckListType => {
  const { inputs } = node;
  const checkResults: {
    type: 'system' | 'input' | 'connection' | 'ifElse' | 'reference' | 'llm' | 'status';
    isValid: boolean;
    message: string;
    details?: any;
  }[] = [];

  const isNeedToCheckInput =
    node.flowNodeType === FlowNodeTypeEnum.tools ||
    node.flowNodeType === FlowNodeTypeEnum.tool ||
    node.flowNodeType === FlowNodeTypeEnum.toolSet;

  // 1. 检查是否为系统节点
  const isSystemNode = [
    FlowNodeTypeEnum.systemConfig,
    FlowNodeTypeEnum.pluginConfig,
    FlowNodeTypeEnum.pluginInput,
    FlowNodeTypeEnum.workflowStart,
    FlowNodeTypeEnum.comment,
    FlowNodeTypeEnum.loopStart,
  ].includes(node.flowNodeType);

  checkResults.push({
    type: 'system',
    isValid: true,
    message: isSystemNode ? '系统节点，跳过检查' : '非系统节点，需要进行完整检查',
    details: { nodeType: node.flowNodeType, isSystemNode },
  });

  // 如果是系统节点，直接返回
  if (isSystemNode) {
    return {
      isValid: true,
      checkResults,
      summary: {
        totalChecks: 1,
        validChecks: 1,
        invalidChecks: 0,
      },
      missingVariableNames: [],
    };
  }

  // 2. 检查 if-else 节点特殊逻辑
  if (node.flowNodeType === FlowNodeTypeEnum.ifElseNode) {
    const ifElseList: IfElseListItemType[] = inputs.find(
      (input) => input.key === NodeInputKeyEnum.ifElseList,
    )?.value;

    const invalidIfElseItems: any[] = [];
    const hasInvalidIfElse = ifElseList?.some((item, itemIndex) => {
      return item.list.some((listItem, listIndex) => {
        const isInvalid =
          listItem.variable === undefined ||
          listItem.condition === undefined ||
          (listItem.value === undefined &&
            listItem.condition !== VariableConditionEnum.isEmpty &&
            listItem.condition !== VariableConditionEnum.isNotEmpty);

        if (isInvalid) {
          invalidIfElseItems.push({
            itemIndex,
            listIndex,
            item: listItem,
            missingFields: {
              variable: listItem.variable === undefined,
              condition: listItem.condition === undefined,
              value:
                listItem.value === undefined &&
                listItem.condition !== VariableConditionEnum.isEmpty &&
                listItem.condition !== VariableConditionEnum.isNotEmpty,
            },
          });
        }
        return isInvalid;
      });
    });

    checkResults.push({
      type: 'ifElse',
      isValid: !hasInvalidIfElse,
      message: hasInvalidIfElse
        ? `If-Else 条件配置不完整，有 ${invalidIfElseItems.length} 个配置项缺失必要字段`
        : 'If-Else 条件配置完整',
      details: { invalidItems: invalidIfElseItems },
    });

    if (hasInvalidIfElse) {
      return {
        isValid: false,
        checkResults,
        summary: {
          totalChecks: checkResults.length,
          validChecks: checkResults.filter((r) => r.isValid).length,
          invalidChecks: checkResults.filter((r) => !r.isValid).length,
        },
        missingVariableNames: invalidIfElseItems
          .map((item) => item.item.variable || `条件${item.itemIndex + 1}-${item.listIndex + 1}`)
          .filter(Boolean),
      };
    }
  }

  // 3. 检查必填输入项
  const invalidInputs: any[] = [];
  const invalidReferenceInputs: any[] = [];
  const missingVariableNames: string[] = [];
  const invalidLLMInputs: any[] = [];

  inputs.forEach((input, index) => {
    // 跳过工具节点的工具描述输入
    if (isNeedToCheckInput) {
      return;
    }

    if (
      input.renderTypeList[input.selectedTypeIndex || 0] === FlowNodeInputTypeEnum.selectLLMModel ||
      input.renderTypeList[input.selectedTypeIndex || 0] === FlowNodeInputTypeEnum.settingLLMModel
    ) {
      const llmModel = llmModelList.find((item) => item.model === input.value);
      if (!llmModel || !llmModel.isActive || !llmModel.isConnect) {
        invalidLLMInputs.push({
          index,
          key: input.key,
          label: input.label || input.debugLabel,
          reason: 'llm_model_error',
          value: input.value,
        });
      }
    }

    // 检查必填项
    if (input.required) {
      const isEmpty =
        (Array.isArray(input.value) && input.value.length === 0) ||
        input.value === undefined ||
        input.value === '';

      if (isEmpty) {
        const variableName = input.label || input.debugLabel || input.key;
        missingVariableNames.push(variableName);
        invalidInputs.push({
          index,
          key: input.key,
          label: input.label || input.debugLabel,
          variableName,
          reason: 'required_empty',
        });
      }
    }

    // 检查引用类型输入
    const renderType = input.renderTypeList[input.selectedTypeIndex || 0];
    if (renderType === FlowNodeInputTypeEnum.reference && input.required) {
      if (!input.value || !Array.isArray(input.value) || input.value.length !== 2) {
        const variableName = input.label || input.debugLabel || input.key;
        if (!missingVariableNames.includes(variableName)) {
          missingVariableNames.push(variableName);
        }
        invalidReferenceInputs.push({
          index,
          key: input.key,
          label: input.label || input.debugLabel,
          variableName,
          reason: 'invalid_reference_format',
          value: input.value,
        });
      } else if (input.value[0] !== VARIABLE_NODE_ID) {
        // 检查引用的源节点是否存在
        const sourceNode = nodes.find((item) => item.data.nodeId === input.value[0]);
        if (!sourceNode) {
          const variableName = input.label || input.debugLabel || input.key;
          if (!missingVariableNames.includes(variableName)) {
            missingVariableNames.push(variableName);
          }
          invalidReferenceInputs.push({
            index,
            key: input.key,
            label: input.label || input.debugLabel,
            variableName,
            reason: 'source_node_not_found',
            value: input.value,
          });
        } else {
          const sourceOutput = sourceNode.data.outputs.find((item) => item.id === input.value[1]);
          if (!sourceOutput) {
            const variableName = input.label || input.debugLabel || input.key;
            if (!missingVariableNames.includes(variableName)) {
              missingVariableNames.push(variableName);
            }
            invalidReferenceInputs.push({
              index,
              key: input.key,
              label: input.label || input.debugLabel,
              variableName,
              reason: 'source_output_not_found',
              value: input.value,
              sourceNode: sourceNode.data.name,
            });
          }
        }
      }
    }
  });

  checkResults.push({
    type: 'input',
    isValid: invalidInputs.length === 0,
    message:
      invalidInputs.length === 0
        ? '所有必填输入项都已填写'
        : `有 ${invalidInputs.length} 个必填输入项未填写: ${missingVariableNames.join(', ')}`,
    details: { invalidInputs, missingVariableNames },
  });

  checkResults.push({
    type: 'llm',
    isValid: invalidLLMInputs.length === 0,
    message:
      invalidLLMInputs.length === 0
        ? '所有模型都可用'
        : `有 ${invalidLLMInputs.length} 个模型不可用: ${invalidLLMInputs
            .map((item) => item.value)
            .join(', ')}`,
    details: { invalidLLMInputs, missingVariableNames },
  });

  checkResults.push({
    type: 'reference',
    isValid: invalidReferenceInputs.length === 0,
    message:
      invalidReferenceInputs.length === 0
        ? '所有引用输入都有效'
        : `有 ${invalidReferenceInputs.length} 个引用输入无效`,
    details: { invalidReferenceInputs },
  });

  if (node.status === NodeStatusEnum.deleted) {
    checkResults.push({
      type: 'status',
      isValid: false,
      message: '节点已失效',
    });
  }

  // 4. 检查节点连接
  const edgeFilted = edges.filter(
    (edge) =>
      !(
        node.flowNodeType === FlowNodeTypeEnum.tools &&
        edge.sourceHandle === NodeOutputKeyEnum.selectedTools
      ),
  );

  const hasEdge = edgeFilted.some(
    (edge) => edge.source === node.nodeId || edge.target === node.nodeId,
  );

  const connectedEdges = edgeFilted.filter(
    (edge) => edge.source === node.nodeId || edge.target === node.nodeId,
  );

  checkResults.push({
    type: 'connection',
    isValid: hasEdge,
    message: hasEdge ? '节点已正确连接' : '节点未连接到工作流',
    details: {
      connectedEdges: connectedEdges.map((edge) => ({
        source: edge.source,
        target: edge.target,
        sourceHandle: edge.sourceHandle,
        targetHandle: edge.targetHandle,
      })),
      edgeCount: connectedEdges.length,
    },
  });

  const isValid = checkResults.every((result) => result.isValid);

  return {
    isValid,
    checkResults,
    summary: {
      totalChecks: checkResults.length,
      validChecks: checkResults.filter((r) => r.isValid).length,
      invalidChecks: checkResults.filter((r) => !r.isValid).length,
    },
    missingVariableNames,
  };
};

/* 检查所有节点，返回详细的检查结果 */
export const checkAllNodesWithDetails = ({
  nodes,
  edges,
  llmModelList = [],
}: {
  nodes: Node<FlowNodeItemType, string | undefined>[];
  edges: Edge<any>[];
  llmModelList: LLMModelItemType[];
}): WorkflowCheckListType => {
  const nodeResults: WorkflowCheckListNodeResultType[] = [];

  const invalidNodes: {
    nodeId: string;
    nodeName: string;
    nodeType: FlowNodeTypeEnum;
    errorTypes: string[];
    missingVariableNames: string[];
  }[] = [];

  const allMissingVariableNames: string[] = [];

  // 遍历所有节点进行检查
  nodes.forEach((node) => {
    // 将 Node 类型转换为 NodeCardProps 类型
    const nodeCardProps: NodeCardProps = {
      ...node.data,
      nodeId: node.data.nodeId,
    };

    const checkResult = checkNodeWithDetails({
      node: nodeCardProps,
      nodes,
      edges,
      llmModelList,
    });

    nodeResults.push({
      nodeId: node.data.nodeId,
      nodeName: node.data.name,
      avatar: node.data.avatar,
      nodeType: node.data.flowNodeType,
      isValid: checkResult.isValid,
      checkResults: checkResult.checkResults,
      summary: checkResult.summary,
      missingVariableNames: checkResult.missingVariableNames,
    });

    // 收集无效节点信息
    if (!checkResult.isValid) {
      const errorTypes = checkResult.checkResults
        .filter((result) => !result.isValid)
        .map((result) => result.type);

      invalidNodes.push({
        nodeId: node.data.nodeId,
        nodeName: node.data.name,
        nodeType: node.data.flowNodeType,
        errorTypes,
        missingVariableNames: checkResult.missingVariableNames,
      });

      // 收集所有缺失的变量名
      checkResult.missingVariableNames.forEach((varName) => {
        if (!allMissingVariableNames.includes(varName)) {
          allMissingVariableNames.push(varName);
        }
      });
    }
  });

  // 计算全局统计信息
  const globalSummary = {
    totalNodes: nodes.length,
    validNodes: nodeResults.filter((result) => result.isValid).length,
    invalidNodes: nodeResults.filter((result) => !result.isValid).length,
    totalChecks: nodeResults.reduce((sum, result) => sum + result.summary.totalChecks, 0),
    validChecks: nodeResults.reduce((sum, result) => sum + result.summary.validChecks, 0),
    invalidChecks: nodeResults.reduce((sum, result) => sum + result.summary.invalidChecks, 0),
  };

  const isValid = invalidNodes.length === 0;

  return {
    isValid,
    nodeResults,
    globalSummary,
    invalidNodes,
    allMissingVariableNames,
  };
};
